package com.ynet.middleground.approve.listener;

import java.util.List;

import org.activiti.engine.HistoryService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.el.FixedValue;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

import com.ynet.core.exception.BusinessException;
import com.ynet.middleground.approve.cmd.SpringContextUtils;

/**
 * @author liulx
 * @description 检查是否已经发现该流程监听，适用于流程开始节点 end 事件配置，添加该监听可根据流程定义Key判断用户是否已经发起某流程
 * @date 2019-12-30 11:07
 */
@DependsOn("springContextUtils")
@Service
public class CheckRepeatedByDefinitionKeyListener extends BaseListener implements ExecutionListener {

    private HistoryService historyService = SpringContextUtils.getBean(HistoryService.class);

    /**
     * 流程模板key
     */
    private FixedValue processDefinitionKey;

    @Override
    public void notify(DelegateExecution delegateExecution) {
        String startUserId = getStartUserId(delegateExecution);
        if (processDefinitionKey == null || StringUtils.isBlank(processDefinitionKey.getExpressionText())) {
            throw new BusinessException("监听器流程定义Key [processDefinitionKey] 不能为空", "ECAP0001");
        }
        String value = processDefinitionKey.getExpressionText();
        if (!allowModify(startUserId, value)) {
            throw new BusinessException("用户已经发起该流程", "ECAP0504");
        }
    }

    /**
     * 允许修改标志
     *
     * @param startUserId
     *            流程发起人
     * @param processDefinitionKey
     *            流程模板标志
     * @return 是否允许修改标志， true: 允许修改; false: 不允许修改
     */
    private boolean allowModify(String startUserId, String processDefinitionKey) {
        List<HistoricProcessInstance> list =
            historyService.createHistoricProcessInstanceQuery().unfinished().startedBy(startUserId)
                .processDefinitionKey(processDefinitionKey).orderByProcessInstanceStartTime().asc().list();
        return (list == null || list.isEmpty());
    }

}
